﻿using ThresholdAssistant.NLogSdk;
using Polly;
using System;
using System.Linq;

namespace ThresholdAssistant.Http.Extensions
{
    /// <summary>
    /// 重试框架扩展
    /// </summary>
    public static class PolicyExtensions
    {
        /// <summary>
        /// 
        /// </summary>
        private static IAsyncPolicy policy;

        /// <summary>
        /// 对象锁
        /// </summary>
        private static readonly object lockObj = new object();

        /// <summary>
        /// 获取配置
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static IAsyncPolicy GetPolicySingle(this object source)
        {
            if (policy == null)
            {
                lock (lockObj)
                {
                    if (policy == null)
                    {
                        //重试配置
                        var sleepDurationList = PollyManager.Config.SleepDurationList.OrderBy(e => e).Select(e => TimeSpan.FromSeconds(e));
                        policy = Policy.Handle<Exception>().WaitAndRetryAsync(sleepDurationList, (ex, timeSpan, context) => NLogUtil.Error($"【Policy重试】TimeSpan：{timeSpan}，发生错误：{ex}"));

                        //多次出错，断路保护
                        IAsyncPolicy policyCir = Policy.Handle<Exception>()
                            .AdvancedCircuitBreakerAsync(
                            failureThreshold: PollyManager.Config.FailureThreshold,
                            minimumThroughput: PollyManager.Config.MinimumThroughput,
                            samplingDuration: TimeSpan.FromSeconds(PollyManager.Config.SamplingDuration),
                            durationOfBreak: TimeSpan.FromSeconds(PollyManager.Config.DurationOfBreakSeconds),
                               onReset: () => NLogUtil.Error($"【Policy断路器关闭】熔断器关闭了！！！"),
                               onHalfOpen: () => NLogUtil.Error($"【Policy断路器半开状态】熔断时间结束时，从断开状态进入半开状态！！！"),
                               onBreak: (ex, breakDelay) => NLogUtil.Error($"【Policy断路器打开】熔断：{breakDelay.TotalMilliseconds} ms，异常：{ex}")
                            );
                        policy = policy.WrapAsync(policyCir);
                    }
                }
            }
            return policy;
        }
    }
}